package com.panopset.io;

import static com.panopset.Util.PERIOD;
import static com.panopset.Util.loadProperties;
import static com.panopset.Util.saveProperties;
import static com.panopset.Util.x;

import java.awt.FileDialog;
import java.io.File;
import java.util.Properties;
import java.util.Vector;

import com.panopset.AbstractApplication;
import com.panopset.Alert;
import com.panopset.Util;
import com.panopset.centralen.resource.PersistentContainer;

/**
 * Manage application properties/defaults.
 *
 * @author Karl Dinwiddie
 *
 */
public final class DocumentManager {

    /**
     * Default file name.
     */
    private final String defaultFileName;

    /**
     * Persistent containers.
     */
    private Vector<PersistentContainer> containers;

    /**
     * Properties to store this document in.
     */
    private final Properties properties = new Properties();

    /**
     * Document manager for this document.
     */
    private static DocumentManager documentManager;

    /**
     * @return Current active DocumentManager
     */
    public static DocumentManager asDocumentManager() {
        if (documentManager == null) {
            documentManager = new DocumentManager();
        }
        return documentManager;
    }

    /**
     * Set document manager.
     * @param newDocumentManager New document manager.
     */
    private static void setDocumentManager(
            final DocumentManager newDocumentManager) {
        documentManager = newDocumentManager;
    }

    /**
     * Constructor. Class name, preceded by a period to make it hidden, is used
     * as default file name
     */
    public DocumentManager() {
        this(PERIOD + DocumentManager.class.getCanonicalName());
    }

    /**
     * Constructor.
     *
     * @param newDefaultFileName
     *            Default file name.
     */
    public DocumentManager(final String newDefaultFileName) {
        defaultFileName = newDefaultFileName;
        setDocumentManager(this);
    }

    /**
     * Constructor.
     *
     * @param clazz
     *            Class is used as a file name, preceded with a period.
     */
    public DocumentManager(final Class<?> clazz) {
        this(PERIOD + clazz.getCanonicalName());
    }

    /**
     * Get application containers.
     *
     * @return Vector of containers.
     */
    public Vector<PersistentContainer> getContainers() {
        if (containers == null) {
            containers = new Vector<PersistentContainer>();
        }
        return containers;
    }

    /**
     * Load properties in to application.
     */
    public void load() {
        loadProperties(properties, getFile());
        for (PersistentContainer container : getContainers()) {
            container.load(properties);
        }
    }

    /**
     * Save application properties in to current document.
     */
    public void save() {
        Alert.yellow(x("Saving..."));
        for (PersistentContainer container : getContainers()) {
            container.flush(properties);
        }
        saveProperties(properties, getFile());
    }

    /**
     * Get properties.
     *
     * @return Properties for the current document.
     */
    public Properties getProperties() {
        return properties;
    }

    /**
     * User new command.
     *
     * @param app Application to save in to new file.
     */
    public void doNew(final AbstractApplication app) {
        File newFile = Util.getFileFromUser(app.getFlexFrame().getFrame(),
                getFile(), x("New file"), FileDialog.SAVE);
        if (newFile != null) {
            setFile(newFile);
            app.getFlexFrame().getFrame().setTitle(
                    app.getApplicationName() + " ~ " + newFile.getName());
            save();
        }
    }

    /**
     * User open command.
     *
     * @param app
     *            Application to open document for.
     */
    public void doOpen(final AbstractApplication app) {
        File newFile = Util.getFileFromUser(app.getFlexFrame().getFrame(),
                getFile(), x("Open file"), FileDialog.LOAD);
        if (newFile != null) {
            setFile(newFile);
            app.getFlexFrame().getFrame().setTitle(
                    app.getApplicationName() + " ~ " + newFile.getName());
            load();
        }
    }

    /**
     * User save command.
     *
     * @param app
     *            Application to save.
     */
    public void doSave(final AbstractApplication app) {
        save();
    }

    /**
     * User save-as command.
     *
     * @param app
     *            Application to save.
     */
    public void doSaveAs(final AbstractApplication app) {
        doNew(app);
        save();
    }

    /**
     * Properties file.
     */
    private File file;

    /**
     * Get properties file.
     *
     * @return File.
     */
    private File getFile() {
        if (file == null) {
            file = new File(defaultFileName);
        }
        return file;
    }

    /**
     * Set file.
     *
     * @param newFile
     *            File to store document properties in.
     */
    public void setFile(final File newFile) {
        file = newFile;
    }

    /**
     * Get value.
     *
     * @param key
     *            Key.
     * @return value.
     */
    public String get(final String key) {
        return getProperties().getProperty(key);
    }

    /**
     *
     * @param key
     *            Key.
     * @param value
     *            Value.
     */
    public void put(final String key, final String value) {
        getProperties().put(key, value);
    }
}
